<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<link rel="stylesheet" href="../style/journal.css" type="text/css" />
<style type="text/css"><!--
.googleadsense {
	margin: 2px;
	padding: 0px;
//--></style><script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-65008-1";
urchinTracker();
</script><title>class Examples11 is Perl6 { ... }</title>
</head>
<body>
<a href="index.html">Journal</a>(2005) | <a href="../blog/"><b>Blog</b></a>(2006) | <a href="http://www.fayland.org/cgi-bin/random_link.pl">RandomLink</a> | <a href="AboutFayland.html">WhoAmI</a> | <a href="LiveBookmark.html">LiveBookmark</a> | <a href="http://www.fayland.org/">HomePage</a>
<p><&lt;Previous: <a href="Perl6_ES10.html">%Examples{'IO'} = open('Perl6');</a>&nbsp;&nbsp;>>Next: <a href="Perl6_ES12.html">$Perl6 = $class.bless(:Example<12>);</a></p>
<h1>class Examples11 is Perl6 { ... }</h1>
<div class='content'>
<p>Category: <a href='Perl6.html'>Perl6</a> &nbsp; Keywords: <b>class Perl6</b></p><h3>Declare</h3>
我开始打算讲 Perl 6 中新的面对对象技术。如果有些新的知识碰到了而前面没讲过，我会穿插着讲点那方面的知识。<br />
最重要的声明是：我不保证我所写的东西是正确的。所以各位看官如果发现错误请给我发电子邮件（fayland at gmail.com）。

<h3>sit down, now comes class. :></h3>
在 Perl 5 中对象，模块，类，包的概念是混在一起的，没有区分开来：
<ul>
<li>一个对象只是一个 bless 的引用
<li>一个类 class 只是一个包 package
<li>一个方法 method 只是一个子程序 sub
<li>一个模块 module 只是一个与 package 名一样的文件
</ul>
<p>在 Perl 6 中他们将都各自拥有自己的关键字。模块有 module 类有 class 方法有 method 对象有 object.</p>

暂时不介绍它们是什么，先讲几个概念：
<ul>
<li>子程序。关键字 sub, 是带有参数列表的不可继承例程。
<li>方法。关键字 method, 是可继承的例程，它总是有一个对应的对象（称之为调用者）和属于一个特定的类。
<li>子方法。关键字 submethod, 是不可继承的方法，或者说是化装成方法的子程序。它也有调用者和所属的特定类。
<li>多重方法/Multimethods. 关键字 multi, 它的特点是可以有一个或多个调用者。
<li>规则。关键字 rule, 是一种用于模式匹配的带语法的方法。它的对应块有特殊的语法。（以后详细说）
<li>宏。关键字 macro, 是一种当它们被解析时（编译时）就运行的例程。宏可能返回另一个源代码字符串或解析树。
<li>角色。关键字 role, 主要用于代码复用。（以后详细说）
</ul>

<h3>class</h3>
先讲类，类主要用于实例（对象）管理，其次才是软件复用（通过继承或委派来实现，我们一般用 role 来实现代码复用）。<br />
<ol>
<li>类是用 class 声明的。它有两种声明方式：
<pre>class Foo;        # 文件下面的部分都是类的定义
...

class Bar {...}    # 块里才是类的定义部分</pre>
我们通过 is 来继承类（可以多重继承），用 does 来复用 role. 简单的例子如下：
<pre>class Dog is Mammal is Pet;  # 继承 Mammal 继承 Pet
class Dog is Mammal does Pet { # Pet 是一个 role

# 另一种方式：
class Dog {
    is Mammal;
    does Pet;
    ...
}</pre>
<li>属性和私有属性。一个简单的例子：
<pre><code>class Dog {
    has $.name is rw; 
    has $.mum; # 没有 is rw 的话只能在 class 里改这个数据
    has $:age; # 私有属性，可以后面加 = 1' 来设置默认值，上面的属性也一样
}

my $pet = Dog.new( :name&lt;Snoopy>, :mum&lt;Kitty>, :age&lt;2> );
# 另一种方式
# my Dog $pet .= new( :name&lt;Snoopy>, :mum&lt;Kitty>, :age&lt;2> );

say $pet.name;  # Snoopy
say $pet.mum;   # Kitty
# say $pet.age; # WRONG, age 为私有变量

$pet.name = 'Shakespeare'; # 设置属性 name 的值
say $pet.name;             # Shakespeare

# $pet.mum = 'Hella';      # WRONG, 默认 mum 是只读的。如果要在类外面更改 mum, 必须设置它为 is rw
</code></pre>
has $.name 类似于生成一个具有同样名字(name)的存取器。<br />
is rw 等后缀属性将复制为存取器的后缀属性。这里的 is rw 将使 name 存取器为左值方法（Lvaule method）。<br />
默认的存取器是只读的。简便设定所有属性为 is rw 的话可以在 class Dog 后加 is rw.
<li>方法和私有方法。我们用 method 来定义方法（我们以前面的例子为基础）：
<pre><code>Class Dog {
    ...
    method grow (?$year = 1) {
        $:age += $year;
        say "$year year past, now $.name is $:age years old";
    }
}
my $pet = Dog.new( :name&lt;Eric>, :age&lt;2> );
$pet.grow; # 1 year past, now Eric is 3 years old
$pet.grow(2); # 2 year past, now Eric is 5 years old

# 除了这种调用方法外，我么还可以这么调用（间接调用）
grow $pet: 2;
grow $pet:(3);</code></pre>
method 其实可以算做 sub 的一种，所不同的是 method 是放在 class/role 里的。<br />
定义私有方法与定义私有属性类似，在方法前加 <b>:</b>. 如 mehod :MyPrivateMethod {...}<br />
甚至定义私有类也可以这样：class :MyPrivateClass {...}

<p>内部方法的调用：</p>
<pre>class Dog {
    has $.name;
    has $:age;
    method grow (?$year = 1) {
        $:age += $year;
        say "$year year past, now $.name is $:age years old";
        .:sigh; # 等同于 $_.:sigh
    }
    method :sigh {
        say "$.name is too old" if ($:age > 7);
    }
}</pre>
<li>类的智能匹配。如果你想确定某一变量是不是某一类的话，可以使用 ~~ 智能匹配。如前面的 $pet：
<pre>if $pet ~~ Dog { say "$pet is a dog"; }</pre>
</ol>

<h3>see u tomorrow</h3>
I'll add something later. have fun!</div>
<p><&lt;Previous: <a href="Perl6_ES10.html">%Examples{'IO'} = open('Perl6');</a>&nbsp;&nbsp;>>Next: <a href="Perl6_ES12.html">$Perl6 = $class.bless(:Example<12>);</a></p>
<p><strong>Options:</strong> <a href='http://del.icio.us/post?title=class%20Examples11%20is%20Perl6%20%7B%20...%20%7D&url=http://www.fayland.org/journal/Perl6_ES11.html'>+Del.icio.us</a></p>
<strong>Related items</strong>
<ul><li><a href='050330.html'>Class::DBI 改 Primary 项</a> < <span class='digit'>2005-03-30 22:27:07</span> ></li><li><a href='Class-Accessor.html'>$Class[0] = 'Class::Accessor';</a> < <span class='digit'>2005-04-26 15:07:30</span> ></li><li><a href='Class-Data-Inheritable.html'>$Class[1] = 'Class::Data::Inheritable';</a> < <span class='digit'>2005-04-27 17:57:39</span> ></li><li><a href='Class-Trigger.html'>$Class[2] = 'Class::Trigger';</a> < <span class='digit'>2005-04-28 16:07:05</span> ></li><li><a href='Perl6_ES12.html'>$Perl6 = $class.bless(:Example<12>);</a> < <span class='digit'>2005-05-31 11:38:46</span> ></li><li><a href='Class_Date.html'>Class::Date 的两个常见用途</a> < <span class='digit'>2005-06-01 15:02:47</span> ></li></ul>
Created on <span class="digit">2005-05-30 13:31:31</span>, Last modified on <span class="digit">2005-05-31 17:55:34</span><br />
Copyright 2004-2005 All Rights Reserved. Powered by <a href="Eplanet.html">Eplanet</a> && <a href='http://catalyst.perl.org'>Catalyst</a> 5.62.
</body>
</html>